package at.tasat.util;

import java.util.BitSet;
import java.util.Iterator;

public class IntSet implements Iterable<Integer> {
	private final int min;
	private final int max;
	private final BitSet bitSet;
	private int size;

	public IntSet(int min, int max) {
		this.min = min;
		this.max = max;
		bitSet = new BitSet(max - min + 1);
		size = 0;
	}

	public void put(int value) {
		assert inRange(value);
		int bitIndex = valueToBitIndex(value);
		if (!bitSet.get(bitIndex)) {
			bitSet.set(bitIndex);
			size++;
		}
	}
	
	public boolean contains(int value){
		assert inRange(value);
		return bitSet.get(valueToBitIndex(value));
	}

	public void clear() {
		bitSet.clear();
		size = 0;
	}

	public int size() {
		return size;
	}

	public void remove(int value) {
		assert inRange(value);
		int bitIndex = valueToBitIndex(value);
		if (bitSet.get(bitIndex)) {
			bitSet.clear(bitIndex);
			size--;
		}
	}
	
	private boolean inRange(int value) {
		return value >= min && value <= max;
	}

	private int valueToBitIndex(int value) {
		return value - min;
	}
	
	private int bitIndexToValue(int bitIndex) {
		return bitIndex + min;
	}

	@Override
	public Iterator<Integer> iterator() {
		return new IntSetIterator();
	}

	private class IntSetIterator implements Iterator<Integer> {
		private int bitIndex;
		private int index;

		private IntSetIterator() {
			bitIndex = -1;
			index = 0;
		}

		@Override
		public boolean hasNext() {
			return index < size;
		}

		@Override
		public Integer next() {
			index++;
			bitIndex = bitSet.nextSetBit(bitIndex + 1);
			return Integer.valueOf(bitIndexToValue(bitIndex));
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}

	}

}
